/**
 * Copyright (c) 2014 S9,Inc.All rights reserved.
 * Created by 2014-10-18 
 */
package cn.jdy.framework.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
/**
 * 二维码（Quick Response Code）
 * @author yangyi
 * @data 2014-10-18
 */
public class QRCodeUtil {
  private static final int BLACK = 0xFF000000; 
  private static final int WHITE = 0xFFFFFFFF; 
  private static final int WIDTH = 200; 
  private static final int HEIGHT = 200; 
   
  private QRCodeUtil() {} 
   
  /**
   * 生成二维码
   * @param text 二维码内的数据，可以是URL，数据等
   * @param path 二维码保存到的路径例如:d:aa/bb/
   * @throws Exception
   */
  public static void getQrCode(String text,String path) throws Exception { 
      //二维码的图片格式 
      String format = "png"; 
      Hashtable hints = new Hashtable(); 
      //内容所使用编码 
      hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); 
      hints.put(EncodeHintType.MARGIN, 1);  //二维码边框宽度，这里文档说设置0-4
      BitMatrix bitMatrix = new MultiFormatWriter().encode(text, 
              BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints); 
      //生成二维码 
      File outputFile = new File(path+File.separator+IDUtil.getID()+".png"); 
      QRCodeUtil.writeToFile(bitMatrix, format, outputFile); 
  }
  
  /**
   * 生成二维码
   * @param text 二维码内的数据，可以是URL，数据等
   * @param path 二维码保存到的路径例如:d:aa/bb/
   * @throws Exception
   */
  public static String getQrCode(HttpServletRequest request,String text) throws Exception { 
    //二维码的图片格式 
    String format = "png"; 
    Hashtable hints = new Hashtable(); 
    //内容所使用编码 
    hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); 
    hints.put(EncodeHintType.MARGIN, 1);  //二维码边框宽度，这里文档说设置0-4
    BitMatrix bitMatrix = new MultiFormatWriter().encode(text, 
        BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints); 
    //生成二维码 
    String img = getDBPath("qrcode")+IDUtil.getID()+".png";
    File outputFile = new File(getRootPath(request) + img); 
    File targetFile = outputFile.getParentFile(); 
    
    if (!targetFile.exists()) {
      targetFile.mkdirs();
    }
    QRCodeUtil.writeToFile(bitMatrix, format, outputFile); 
    return img;
  }
  
  /**
   * 获取文件存储 目录
   * 获取webapps目录的绝对路径
   * @return
   */
  public static String getRootPath(HttpServletRequest request){
    String path = request.getSession().getServletContext().getRealPath("/");// 获取项目部署目录
    return new File(path).getParent();
  }
  
  /**
   * 获取文件存储 目录
   * @param type 目录类别
   * /fileRoot/savePath/yyyyMMdd/
   * @return
   */
  public static String getDBPath(String typeName){
    String fileRoot = "/upload";// 根目录
    SimpleDateFormat formater = new SimpleDateFormat("yyyyMMdd");
    String dateDir = formater.format(new Date());
    String dbPath = fileRoot + "/" + typeName + "/" + dateDir + "/";
    return dbPath;
  }
  /**
   * 生成二维码
   * @param text
   * @param width
   * @param height
   * @param stream
   * @throws Exception
   */
  public static void getQrCode(String text,OutputStream stream) throws Exception { 
    //二维码的图片格式 
    String format = "png"; 
    Hashtable hints = new Hashtable(); 
    //内容所使用编码 
    hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); 
    hints.put(EncodeHintType.MARGIN, 1);  //二维码边框宽度，这里文档说设置0-4
    BitMatrix bitMatrix = new MultiFormatWriter().encode(text, 
        BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints); 
    QRCodeUtil.writeToStream(bitMatrix, format, stream);
  } 
     
  /**
   * 生成二维码图片
   * @param matrix
   * @return
   */
  private static BufferedImage toBufferedImage(BitMatrix matrix) { 
    int width = matrix.getWidth(); 
    int height = matrix.getHeight(); 
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
    for (int x = 0; x < width; x++) { 
      for (int y = 0; y < height; y++) { 
        image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); 
      } 
    } 
    return image; 
  } 
   
     
  /**
   * 将生成的二维码写入到磁盘文件
   * @param matrix
   * @param format
   * @param file
   * @throws IOException
   */
  private static void writeToFile(BitMatrix matrix, String format, File file) 
      throws IOException { 
    BufferedImage image = toBufferedImage(matrix); 
    if (!ImageIO.write(image, format, file)) { 
      throw new IOException("Could not write an image of format " + format + " to " + file); 
    } 
  } 
   
     
  /**
   * 将生成的二位码通过输出流输出
   * @param matrix
   * @param format
   * @param stream
   * @throws IOException
   */
  private static void writeToStream(BitMatrix matrix, String format, OutputStream stream) 
      throws IOException { 
    BufferedImage image = toBufferedImage(matrix); 
    if (!ImageIO.write(image, format, stream)) { 
      throw new IOException("Could not write an image of format " + format); 
    } 
  } 
  
}
